package org.simpleflatmapper.datastax.test.impl;
import com.datastax.driver.core.*;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.ReadablePartial;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.simpleflatmapper.datastax.impl.SettableDataSetterFactory;
import org.simpleflatmapper.test.beans.DbObject;
import org.simpleflatmapper.datastax.DatastaxColumnKey;
import org.simpleflatmapper.map.MapperConfig;
import org.simpleflatmapper.map.property.FieldMapperColumnDefinition;
import org.simpleflatmapper.map.property.TimeZoneProperty;
import org.simpleflatmapper.converter.joda.JodaDateTimeZoneProperty;
//IFJAVA8_START
import org.simpleflatmapper.map.property.time.JavaZoneIdProperty;
//IFJAVA8_END
import org.simpleflatmapper.map.mapper.ColumnDefinition;
import org.simpleflatmapper.map.mapper.PropertyMapping;
import org.simpleflatmapper.reflect.ReflectionService;
import org.simpleflatmapper.reflect.Setter;
import org.simpleflatmapper.util.TypeReference;
import org.simpleflatmapper.reflect.meta.PropertyMeta;
import org.simpleflatmapper.reflect.primitive.DoubleSetter;
import org.simpleflatmapper.reflect.primitive.FloatSetter;
import org.simpleflatmapper.reflect.primitive.IntSetter;
import org.simpleflatmapper.reflect.primitive.LongSetter;
import org.simpleflatmapper.tuple.Tuple2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
//IFJAVA8_START
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.MonthDay;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
//IFJAVA8_END
import java.util.*;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SuppressWarnings("unchecked")
public class SettableDataSetterFactoryTest {
private final MapperConfig<DatastaxColumnKey, FieldMapperColumnDefinition<DatastaxColumnKey>> mapperConfig = MapperConfig.<DatastaxColumnKey>fieldMapperConfig();
private final ReflectionService reflectionService = ReflectionService.newInstance();
SettableDataSetterFactory factory = new SettableDataSetterFactory(mapperConfig, reflectionService);
private int index;
SettableData statement;
@Before
public void setUp() {
statement = mock(BoundStatement.class);
index = 0;
}
@Test
public void testUDT() throws Exception {
UserType ut = newDBObjectUserType();
Setter<SettableByIndexData, DbObject> setter = factory.getSetter(newPM(DbObject.class, ut));
DbObject object = DbObject.newInstance();
setter.set(statement, object);
ArgumentCaptor<UDTValue> argumentCaptor = ArgumentCaptor.forClass(UDTValue.class);
verify(statement).setUDTValue(eq(0), argumentCaptor.capture());
UDTValue value = argumentCaptor.getValue();
assertUdtEqualsDbObject(value, object);
setter.set(statement, null);
verify(statement).setToNull(0);
}
protected void assertUdtEqualsDbObject(UDTValue value, DbObject object) {
assertEquals(object.getId(), value.getLong(0));
assertEquals(object.getName(), value.getString(1));
assertEquals(object.getEmail(), value.getString(2));
assertEquals(object.getCreationTime(), value.getDate(3));
assertEquals(object.getTypeName().name(), value.getString(4));
assertEquals(object.getTypeOrdinal().ordinal(), value.getInt(5));
}
protected UserType newDBObjectUserType() throws Exception {
UserType.Field id = newField("id", DataType.bigint());
UserType.Field name = newField("name", DataType.text());
UserType.Field email = newField("email", DataType.text());
UserType.Field creationTime = newField("creation_time", DataType.timestamp());
UserType.Field typeName = newField("type_name", DataType.text());
UserType.Field typeOrdinal = newField("type_ordinal", DataType.cint());
return newUserType(id, name, email, creationTime, typeName, typeOrdinal);
}
private UserType newUserType(UserType.Field... fields) throws Exception {
Constructor<?> constructor = UserType.class.getDeclaredConstructor(String.class, String.class, Collection.class);
constructor.setAccessible(true);
return (UserType) constructor.newInstance("ks", "name", Arrays.asList(fields));
}
private UserType.Field newField(String name, DataType type) throws Exception {
Constructor<?> constructor = UserType.Field.class.getDeclaredConstructor(String.class, DataType.class);
constructor.setAccessible(true);
return (UserType.Field) constructor.newInstance(name, type);
}
@Test
public void testUDTValue() throws Exception {
UDTValue bd = mock(UDTValue.class);
UserType udtType = mock(UserType.class);
Setter<SettableByIndexData, UDTValue> setter = factory.getSetter(newPM(UDTValue.class, udtType));
setter.set(statement, bd);
setter.set(statement, null);
verify(statement).setUDTValue(0, bd);
verify(statement).setToNull(0);
}
@Test
public void testSet() throws Exception {
Set<String> values = new HashSet<String>(Arrays.asList("v1", "v2"));
Setter<SettableByIndexData, Set<String>> setter = factory.getSetter(newPM(new TypeReference<Set<String>>() {}.getType(), DataType.set(DataType.text())));
setter.set(statement, values);
setter.set(statement, null);
verify(statement).setSet(0, values);
verify(statement).setToNull(0);
}
@Test
public void testSetOfTuple() throws Exception {
TupleType ut = TupleType.of(DataType.text(), DataType.cint());
Set<Tuple2<String, Integer>> values =
new HashSet<Tuple2<String, Integer>>(
Arrays.asList(new Tuple2<String, Integer>("aa", 1),
new Tuple2<String, Integer>("bb", 2))) ;
Setter<SettableByIndexData, Set<Tuple2<String, Integer>>> setter = factory.getSetter(newPM(new TypeReference<Set<Tuple2<String, Integer>>>() {}.getType(), DataType.set(ut)));
setter.set(statement, values);
setter.set(statement, null);
ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class);
verify(statement).setSet(eq(0), captor.capture());
Set value = captor.getValue();
assertEquals(2, value.size());
for(Object o : value) {
TupleValue tv = (TupleValue) o;
String str = tv.getString(0);
int i = tv.getInt(1);
switch (i) {
case 1:
assertEquals("aa", str);
break;
case 2:
assertEquals("bb", str);
break;
default: fail();
}
}
verify(statement).setToNull(0);
}
@Test
public void testList() throws Exception {
List<String> values = Arrays.asList("v1", "v2");
Setter<SettableByIndexData, List<String>> setter = factory.getSetter(newPM(new TypeReference<List<String>>() {}.getType(), DataType.list(DataType.text())));
setter.set(statement, values);
setter.set(statement, null);
verify(statement).setList(0, values);
verify(statement).setToNull(0);
}
@Test
public void testListOfUDT() throws Exception {
UserType ut = newDBObjectUserType();
List<DbObject> values = Arrays.asList(DbObject.newInstance(), DbObject.newInstance());
Setter<SettableByIndexData, List<DbObject>> setter = factory.getSetter(newPM(new TypeReference<List<DbObject>>() {}.getType(), DataType.list(ut)));
setter.set(statement, values);
setter.set(statement, null);
ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
verify(statement).setList(eq(0), captor.capture());
assertUdtEqualsDbObject((UDTValue) captor.getValue().get(0), values.get(0));
assertUdtEqualsDbObject((UDTValue) captor.getValue().get(1), values.get(1));
verify(statement).setToNull(0);
}
@Test
public void testMap() throws Exception {
DataType map = DataType.map(DataType.text(), DataType.text());
Map<String, String> values = new HashMap<String, String>();
values.put("aa", "bb");
Setter<SettableByIndexData, Map<String, String>> setter = factory.getSetter(newPM(new TypeReference<Map<String, String>>() {}.getType(), map));
setter.set(statement, values);
setter.set(statement, null);
verify(statement).setMap(0, values);
verify(statement).setToNull(0);
}
@Test
public void testMapWithConverter() throws Exception {
TupleType ut = TupleType.of(DataType.text(), DataType.cint());
DataType map = DataType.map(DataType.text(), ut);
Map<Integer, Tuple2<String, Integer>> values = new HashMap<Integer, Tuple2<String, Integer>>();
values.put(1, new Tuple2<String, Integer>("aa", 2));
Setter<SettableByIndexData, Map<Integer, Tuple2<String, Integer>>> setter = factory.getSetter(newPM(new TypeReference<Map<Integer, Tuple2<String, Integer>>>() {}.getType(), map));
setter.set(statement, values);
setter.set(statement, null);
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class);
verify(statement).setMap(eq(0), captor.capture());
Map value = captor.getValue();
assertEquals(1, value.size());
TupleValue tv = (TupleValue) value.get("1");
assertEquals("aa", tv.getString(0));
assertEquals(2, tv.getInt(1));
verify(statement).setToNull(0);
}
@Test
public void testTuple() throws Exception {
TupleType tupleType = TupleType.of(DataType.text(), DataType.cint());
TupleValue bd = tupleType.newValue("vvv", 15);
Setter<SettableByIndexData, Tuple2> setter = factory.getSetter(newPM(new TypeReference<Tuple2<String, Integer>>() {}.getType(), tupleType));
setter.set(statement, new Tuple2<String, Integer>("vvv", 15));
setter.set(statement, null);
verify(statement).setTupleValue(0, bd);
verify(statement).setToNull(0);
}
@Test
public void testTupleValue() throws Exception {
TupleValue bd = mock(TupleValue.class);
Setter<SettableByIndexData, TupleValue> setter = factory.getSetter(newPM(TupleValue.class, TupleType.of(DataType.text(), DataType.text())));
setter.set(statement, bd);
setter.set(statement, null);
verify(statement).setTupleValue(0, bd);
verify(statement).setToNull(0);
}
@Test
public void testBigDecimal() throws Exception {
BigDecimal bd = new BigDecimal("3.33");
Setter<SettableByIndexData, BigDecimal> setter = factory.getSetter(newPM(BigDecimal.class, DataType.decimal()));
setter.set(statement, bd);
setter.set(statement, null);
verify(statement).setDecimal(0, bd);
verify(statement).setToNull(0);
}
@Test
public void testBigInteger() throws Exception {
BigInteger bi = new BigInteger("333");
Setter<SettableByIndexData, BigInteger> setter = factory.getSetter(newPM(BigInteger.class, DataType.varint()));
setter.set(statement, bi);
setter.set(statement, null);
verify(statement).setVarint(0, bi);
verify(statement).setToNull(0);
}
@Test
public void testInetAddress() throws Exception {
InetAddress inetAddress = InetAddress.getByAddress(new byte[] {127, 0, 0, 1});
Setter<SettableByIndexData, InetAddress> setter = factory.getSetter(newPM(InetAddress.class, DataType.inet()));
setter.set(statement, inetAddress);
setter.set(statement, null);
verify(statement).setInet(0, inetAddress);
verify(statement).setToNull(0);
}
@Test
public void testUUID() throws Exception {
UUID value = UUID.randomUUID();
Setter<SettableByIndexData, UUID> setter = factory.getSetter(newPM(UUID.class, DataType.uuid()));
setter.set(statement, value);
setter.set(statement, null);
verify(statement).setUUID(0, value);
verify(statement).setToNull(0);
}
@Test
public void testUUIDFromString() throws Exception {
UUID value = UUID.randomUUID();
Setter<SettableByIndexData, String> setter = factory.getSetter(newPM(String.class, DataType.uuid()));
setter.set(statement, value.toString());
setter.set(statement, null);
verify(statement).setUUID(0, value);
verify(statement).setToNull(0);
}
@Test
public void testByteSetter() throws Exception {
Setter<SettableByIndexData, Byte> setter = factory.getSetter(newPM(byte.class, DataType.cint()));
setter.set(statement, (byte)3);
setter.set(statement, null);
verify(statement).setInt(0, 3);
verify(statement).setToNull(0);
}
@Test
public void testShortSetter() throws Exception {
Setter<SettableByIndexData, Short> setter = factory.getSetter(newPM(short.class, DataType.cint()));
setter.set(statement, (short)3);
setter.set(statement, null);
verify(statement).setInt(0, 3);
verify(statement).setToNull(0);
}
@Test
public void testFloatSetter() throws Exception {
Setter<SettableByIndexData, Float> setter = factory.getSetter(newPM(float.class, DataType.cfloat()));
assertTrue(setter instanceof FloatSetter);
setter.set(statement, 3.0f);
setter.set(statement, null);
verify(statement).setFloat(0, 3.0f);
verify(statement).setToNull(0);
}
@Test
public void testDoubleSetter() throws Exception {
Setter<SettableByIndexData, Double> setter = factory.getSetter(newPM(double.class, DataType.cdouble()));
assertTrue(setter instanceof DoubleSetter);
setter.set(statement, 3.0);
setter.set(statement, null);
verify(statement).setDouble(0, 3.0);
verify(statement).setToNull(0);
}
@Test
public void testIntSetter() throws Exception {
Setter<SettableByIndexData, Integer> setter = factory.getSetter(newPM(int.class, DataType.cint()));
assertTrue(setter instanceof IntSetter);
setter.set(statement, 3);
setter.set(statement, null);
verify(statement).setInt(0, 3);
verify(statement).setToNull(0);
}
@Test
public void testIntSetterWithLongSource() throws Exception {
Setter<SettableByIndexData, Long> setter = factory.getSetter(newPM(long.class, DataType.cint()));
setter.set(statement, 3l);
setter.set(statement, null);
verify(statement).setInt(0, 3);
verify(statement).setToNull(0);
}
@Test
public void testLongSetterWithIntSource() throws Exception {
Setter<SettableByIndexData, Integer> setter = factory.getSetter(newPM(int.class, DataType.bigint()));
setter.set(statement, 3);
setter.set(statement, null);
verify(statement).setLong(0, 3l);
verify(statement).setToNull(0);
}
@Test
public void testLongSetter() throws Exception {
Setter<SettableByIndexData, Long> setter = factory.getSetter(newPM(long.class, DataType.bigint()));
assertTrue(setter instanceof LongSetter);
setter.set(statement, 3l);
setter.set(statement, null);
verify(statement).setLong(0, 3l);
verify(statement).setToNull(0);
}
@Test
public void testStringSetter() throws Exception {
Setter<SettableByIndexData, String> setter = factory.getSetter(newPM(String.class, DataType.text()));
setter.set(statement, "str");
setter.set(statement, null);
verify(statement).setString(0, "str");
verify(statement).setToNull(0);
}
@Test
public void tesDate() throws Exception {
Setter<SettableByIndexData, Date> setter = factory.getSetter(newPM(Date.class, DataType.timestamp()));
Date date = new Date();
setter.set(statement, date);
setter.set(statement, null);
verify(statement).setDate(0, date);
verify(statement).setToNull(0);
}
//IFJAVA8_START
@Test
public void testJava8TimeLDT() throws Exception {
Setter<SettableByIndexData, LocalDateTime> setter = factory.getSetter(newPM(LocalDateTime.class, DataType.timestamp()));
LocalDateTime ldt = LocalDateTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant()));
verify(statement).setToNull(0);
final ZoneId zoneId = ZoneId.ofOffset("UTC", ZoneOffset.ofHours(2));
Setter<SettableByIndexData, LocalDateTime> setterTz = factory.getSetter(newPM(LocalDateTime.class, DataType.timestamp(), new JavaZoneIdProperty(zoneId)));
setterTz.set(statement, ldt);
verify(statement).setDate(1, Date.from(ldt.atZone(zoneId).toInstant()));
}
@Test
public void testJava8TimeLD() throws Exception {
Setter<SettableByIndexData, LocalDate> setter = factory.getSetter(newPM(LocalDate.class, DataType.timestamp()));
LocalDate ldt = LocalDate.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atStartOfDay(ZoneId.systemDefault()).toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeLT() throws Exception {
Setter<SettableByIndexData, LocalTime> setter = factory.getSetter(newPM(LocalTime.class, DataType.timestamp()));
LocalTime ldt = LocalTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeODT() throws Exception {
Setter<SettableByIndexData, OffsetDateTime> setter = factory.getSetter(newPM(OffsetDateTime.class, DataType.timestamp()));
OffsetDateTime ldt = OffsetDateTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeOT() throws Exception {
Setter<SettableByIndexData, OffsetTime> setter = factory.getSetter(newPM(OffsetTime.class, DataType.timestamp()));
OffsetTime ldt = OffsetTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atDate(LocalDate.now()).toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeZDT() throws Exception {
Setter<SettableByIndexData, ZonedDateTime> setter = factory.getSetter(newPM(ZonedDateTime.class, DataType.timestamp()));
ZonedDateTime ldt = ZonedDateTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeYearMonth() throws Exception {
Setter<SettableByIndexData, YearMonth> setter = factory.getSetter(newPM(YearMonth.class, DataType.timestamp()));
YearMonth ldt = YearMonth.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atDay(1).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeYear() throws Exception {
Setter<SettableByIndexData, Year> setter = factory.getSetter(newPM(Year.class, DataType.timestamp()));
Year ldt = Year.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt.atMonthDay(MonthDay.of(Month.JANUARY, 1)).atStartOfDay(ZoneId.systemDefault()).toInstant()));
verify(statement).setToNull(0);
}
@Test
public void testJava8TimeInstant() throws Exception {
Setter<SettableByIndexData, Instant> setter = factory.getSetter(newPM(Instant.class, DataType.timestamp()));
Instant ldt = Instant.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, Date.from(ldt));
verify(statement).setToNull(0);
}
//IFJAVA8_END
@Test
public void testJodaLDT() throws Exception {
long time = System.currentTimeMillis();
testJodaDate(new org.joda.time.LocalDateTime(time), new Date(time));
}
private <T extends ReadablePartial> void testJodaDate(T joda, Date date) throws Exception {
Setter<SettableByIndexData, T> setter = factory.getSetter(newPM(joda.getClass(), DataType.timestamp()));
setter.set(statement, joda);
verify(statement).setDate(0, date);
setter.set(statement, null);
verify(statement).setToNull(0);
DateTimeZone tz2 = getNonDefaultDateTimeZone(date);
Setter<SettableByIndexData, T> setterTZ =
factory.getSetter(newPM(joda.getClass(), DataType.timestamp(), new JodaDateTimeZoneProperty(tz2)));
setterTZ.set(statement, joda);
verify(statement).setDate(1, new Date(date.getTime() + TimeUnit.HOURS.toMillis(2)));
TimeZone jtz = tz2.toTimeZone();
Setter<SettableByIndexData, T> setterJTZ =
factory.getSetter(newPM(joda.getClass(), DataType.timestamp(), new TimeZoneProperty(jtz)));
setterJTZ.set(statement, joda);
verify(statement).setDate(1, new Date(date.getTime() + TimeUnit.HOURS.toMillis(2)));
}
private DateTimeZone getNonDefaultDateTimeZone(Date date) {
return DateTimeZone.forOffsetHours((int) (TimeUnit.MILLISECONDS.toHours(DateTimeZone.getDefault().getOffset(date.getTime())) - 2));
}
@Test
public void testJodaDT() throws Exception {
Setter<SettableByIndexData, org.joda.time.DateTime> setter = factory.getSetter(newPM(org.joda.time.DateTime.class, DataType.timestamp()));
org.joda.time.DateTime ldt = org.joda.time.DateTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, ldt.toDate());
verify(statement).setToNull(0);
}
@Test
public void testJodaLD() throws Exception {
Setter<SettableByIndexData, org.joda.time.LocalDate> setter = factory.getSetter(newPM(org.joda.time.LocalDate.class, DataType.timestamp()));
org.joda.time.LocalDate ldt = org.joda.time.LocalDate.now();
setter.set(statement, ldt);
setter.set(statement, null);
verify(statement).setDate(0, ldt.toDate());
verify(statement).setToNull(0);
}
@Test
public void testJodaLT() throws Exception {
Setter<SettableByIndexData, org.joda.time.LocalTime> setter = factory.getSetter(newPM(org.joda.time.LocalTime.class, DataType.timestamp()));
org.joda.time.LocalTime ldt = org.joda.time.LocalTime.now();
setter.set(statement, ldt);
setter.set(statement, null);
final Date date = ldt.toDateTimeToday().toDate();
verify(statement).setDate(0, date);
verify(statement).setToNull(0);
DateTimeZone tz2 = getNonDefaultDateTimeZone(date);
DateTime dateTime = ldt.toDateTimeToday(tz2);
final Date dateTz = dateTime.toDate();
Setter<SettableByIndexData, org.joda.time.LocalTime> setterTZ =
factory.getSetter(newPM(org.joda.time.LocalTime.class, DataType.timestamp(), new JodaDateTimeZoneProperty(tz2)));
setterTZ.set(statement, ldt);
verify(statement).setDate(1, new Date(dateTz.getTime()));
}
@Test
public void testJodaInstant() throws Exception {
Setter<SettableByIndexData, org.joda.time.Instant> setter = factory.getSetter(newPM(org.joda.time.Instant.class, DataType.timestamp()));
org.joda.time.Instant ldt = org.joda.time.Instant.now();
setter.set(statement, ldt);
setter.set(statement, null);
final Date date = ldt.toDate();
verify(statement).setDate(0, date);
verify(statement).setToNull(0);
}
@SuppressWarnings("unchecked")
private <T, P> PropertyMapping<?, ?, DatastaxColumnKey, ? extends ColumnDefinition<DatastaxColumnKey, ?>> newPM(Type clazz, DataType datatype, Object... properties) {
PropertyMeta<T, P> propertyMeta = mock(PropertyMeta.class);
when(propertyMeta.getPropertyType()).thenReturn(clazz);
return
new PropertyMapping<T, P, DatastaxColumnKey, FieldMapperColumnDefinition<DatastaxColumnKey>>(
propertyMeta,
new DatastaxColumnKey("col", index++, datatype),
FieldMapperColumnDefinition.<DatastaxColumnKey>of(properties));
}
}